package pro.shushi.pamirs.hr.core.action;

import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import pro.shushi.pamirs.framework.connectors.data.sql.query.QueryWrapper;
import pro.shushi.pamirs.hr.api.enums.HrEmployeeStatusEnum;
import pro.shushi.pamirs.hr.api.model.org.Employee;
import pro.shushi.pamirs.meta.annotation.Action;
import pro.shushi.pamirs.meta.annotation.Function;
import pro.shushi.pamirs.meta.annotation.Model;
import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
import pro.shushi.pamirs.meta.api.dto.common.Message;
import pro.shushi.pamirs.meta.api.dto.condition.Pagination;
import pro.shushi.pamirs.meta.api.session.PamirsSession;
import pro.shushi.pamirs.meta.constant.ExpConstants;
import pro.shushi.pamirs.meta.constant.FunctionConstants;
import pro.shushi.pamirs.meta.enmu.*;

import java.util.List;

/**
 * 自定义方法实现如果复杂，建议抽取服务到Service中。参考EmployeeBatchReqAction
 *
 * EmployeeAction是模拟覆盖所有系统默认的Action + 自定义动作 的示例
 */
@Slf4j
@Component
@Model.model(Employee.MODEL_MODEL)
public class EmployeeAction {

    /**
     * 自定义构造方法示例
     * 如：界面设计器提交数据-选择的提交函数，新增时系统会调用construct
     * @param data
     * @return
     */
    @Function(openLevel = FunctionOpenEnum.API)
    @Function.Advanced(type = FunctionTypeEnum.QUERY)
    public Employee construct(Employee data) {
        // TODO: 可增加处理逻辑；一般构造页面的初始数据
        return data;
    }

    /**Start--重写覆盖系统默认增删改查的实现方式---------------------------------------------------------------------*/
    // 重写默认的查询列表函数(如果默认满足则不需要重写)。该示例重新员工改变排序规则
    @Function.Advanced(type = FunctionTypeEnum.QUERY, displayName = "查询列表")
    @Function.fun(FunctionConstants.queryPage)
    @Function(openLevel = {FunctionOpenEnum.API})
    public Pagination<Employee> queryPage(Pagination<Employee> page, QueryWrapper<Employee> queryWrapper) {
        // 该示例列举自定义排序规则：参考：https://doc.oinone.top/backend/11449.html
        // 1、平台默认排序字段，按创建时间和ID倒序(ordering = "createDate DESC, id DESC"), 可以修改模型ordering定义改变排序规则
        // 2、关闭排序(设置不排序) page.setSortable(Boolean.FALSE);
        // 3、指定排序字段        page.orderBy(SortDirectionEnum.DESC, Employee::getEntryDate);
        page.orderBy(SortDirectionEnum.DESC, Employee::getEntryDate);
        return new Employee().queryPage(page, queryWrapper);
    }

    // 重写默认的新增保存函数(如果默认满足则不需要重写)
    @Transactional
    @Action.Advanced(name = FunctionConstants.create, managed = true, invisible = ExpConstants.idValueExist)
    @Action(displayName = "保存", summary = "创建", bindingType = ViewTypeEnum.FORM)
    @Function(name = FunctionConstants.create)
    @Function.fun(FunctionConstants.create)
    public Employee create(Employee data) {
        // construct()方法,如果字段没有赋值的情况会把defaultValue赋上
        data.construct();
        data.create();
        // 如果create重写了，关系型字段需要手动save
        data.fieldSave(Employee::getExtraPositions);
        return data;
    }

    // 重写默认的更新保存函数(如果默认满足则不需要重写)
    @Transactional
    @Function.Advanced(type = FunctionTypeEnum.UPDATE)
    @Action.Advanced(name = FunctionConstants.update, managed = true, invisible = ExpConstants.idValueNotExist)
    @Action(displayName = "更新", summary = "修改", bindingType = ViewTypeEnum.FORM)
    @Function(name = FunctionConstants.update)
    @Function.fun(FunctionConstants.update)
    public Employee update(Employee data) {
        data.updateById();
        // 如果create重写了，关系型字段需要手动save
        data.fieldSave(Employee::getExtraPositions);
        return data;
    }

    // 重写默认的查询单条记录(如果默认满足则不需要重写)
    @Function.Advanced(type= FunctionTypeEnum.QUERY)
    @Function.fun(FunctionConstants.queryByEntity)
    @Function(openLevel = {FunctionOpenEnum.API})
    public Employee queryOne(Employee query){
        return query.queryById();
    }

    // 重写 批量删除函数(如果默认满足则不需要重写)
    @Action(displayName = "删除", contextType = ActionContextTypeEnum.SINGLE_AND_BATCH)
    @Function(name = FunctionConstants.delete)
    @Function.fun(FunctionConstants.deleteWithFieldBatch)
    @Function.Advanced(type = FunctionTypeEnum.DELETE)
    public List<Employee> delete(List<Employee> dataList) {
        for (Employee employee : dataList) {
            employee.deleteById();
        }
        return dataList;
    }
    /**End--重写覆盖系统默认增删改查的实现方式---------------------------------------------------------------------*/

    // 自定义Action，只需要加上Action注解即可
    @Action(displayName = "转正", bindingType = ViewTypeEnum.TABLE, contextType = ActionContextTypeEnum.SINGLE)
    // 可以在界面设计器设置如果是非NC状态按钮隐藏掉或者无效
    @Action.Advanced(invisible = "activeRecord.employeeStatus != 'TRUN'")
    public Employee entry(Employee employee) {
        Employee upEmployee = new Employee();
        upEmployee.setId(employee.getId());
        upEmployee.setEmployeeStatus(HrEmployeeStatusEnum.ENTRY);
        upEmployee.updateById();
        PamirsSession.getMessageHub().info("操作转正成功");
        return employee;
    }

    // 自定义Action，只需要加上Action注解即可
    @Action(displayName = "离职", bindingType = ViewTypeEnum.TABLE, contextType = ActionContextTypeEnum.SINGLE)
    // 可以在界面设计器设置如果是非NC状态按钮隐藏掉或者无效
    @Action.Advanced(invisible = "activeRecord.employeeStatus != 'ENTRY'")
    public Employee quitted(Employee employee) {
        Employee upEmployee = new Employee();
        upEmployee.setId(employee.getId());
        upEmployee.setEmployeeStatus(HrEmployeeStatusEnum.QUITTED);
        upEmployee.updateById();
        PamirsSession.getMessageHub().info("操作离职成功");
        return employee;
    }

    /**
     * 测试各种信息提示；测试各种信息提示
     * @param data
     * @return
     */
    @Action(displayName = "提示信息示例",bindingType = ViewTypeEnum.TABLE,contextType = ActionContextTypeEnum.CONTEXT_FREE)
    public Employee message(Employee data){
        // PamirsSession.getMessageHub().info("info-模拟信息提示");
        // PamirsSession.getMessageHub().error("error-模拟错误提示");
        // PamirsSession.getMessageHub().msg(new Message().msg("success-模拟成功提示").setLevel(InformationLevelEnum.SUCCESS));
        // PamirsSession.getMessageHub().msg(new Message().msg("debug-模拟调试提示").setLevel(InformationLevelEnum.DEBUG));
        PamirsSession.getMessageHub().msg(new Message().msg("warn-模拟警告提示").setLevel(InformationLevelEnum.WARN));
        return data;
    }

}
